from typing import Generic, TypeVar, Optional, List
from pydantic import BaseModel
from motor.motor_asyncio import AsyncIOMotorDatabase
from models.base import MongoBaseModel

# ModelType：表示数据库模型类型，必须继承自MongoBaseModel（自定义的 MongoDB 模型基类）
ModelType = TypeVar("ModelType", bound=MongoBaseModel)

# 这是一个泛型类，接受三个类型参数
class BaseRepository(Generic[ModelType]):
    def __init__(self, collection_name: str, db: AsyncIOMotorDatabase):
        """
        初始化时需要指定 MongoDB 集合名称和数据库连接
        通过db[collection_name]获取 MongoDB 集合对象
        """
        self.collection = db[collection_name]
        self.collection_name = collection_name

    async def get(self, id: str) -> Optional[ModelType]:
        obj = await self.collection.find_one({"_id": id})
        if obj:
            return ModelType(**obj)
        return None

    async def create(self, obj_in: ModelType) -> ModelType:
        obj_dict = obj_in.model_dump()
        result = await self.collection.insert_one(obj_dict)
        created_obj = await self.collection.find_one({"_id": result.inserted_id})
        return ModelType(**created_obj)

    async def update(self, id: str, obj_in: ModelType) -> Optional[ModelType]:
        obj_dict = {k: v for k, v in obj_in.model_dump().items() if v is not None}
        if not obj_dict:
            return None
        await self.collection.update_one({"_id": id}, {"$set": obj_dict})
        updated_obj = await self.collection.find_one({"_id": id})
        return ModelType(**updated_obj) if updated_obj else None

    async def delete(self, id: str) -> bool:
        result = await self.collection.delete_one({"_id": id})
        return result.deleted_count == 1

    async def list(self, skip: int = 0, limit: int = 100) -> List[ModelType]:
        objs = []
        async for obj in self.collection.find().skip(skip).limit(limit):
            objs.append(ModelType(**obj))
        return objs    